home *** CD-ROM | disk | FTP | other *** search
- /*
- File: PCCardClient.c
-
- Contains: Card-independent portion of the PC Card Sample Client
-
- Written by: Dave Falkenburg with lots of helpful code from:
- Phillip Nguyen, Greg Brewer, timothy warden,
- James Blair, Mark D. Rustad, and Richard W. Mincher.
-
- Copyright © 1995 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <0> 11/28/95 DRF first code.
- */
-
- #include "PCCardClient.h"
-
- #include <Resources.h>
- #include <ToolUtils.h>
- #include <Gestalt.h>
-
-
- // internal utility functions
-
- static void CopyPStringToBoundedCString(StringPtr sourcePString,char * destCString,UInt16 *size);
- static void SetClientEventMaskForSocket(PCCardClientGlobalsRec * globals, UInt16 socket, UInt16 eventMask);
- static pascal OSErr DetachIcons(ResType resType, Handle *hdl, void * param);
-
-
-
- #if GENERATINGPOWERPC
- unsigned long __procinfo = kPascalStackBased;
- #endif
-
- void
- main()
- {
- Handle me = GetResource('INIT',128);
- UInt32 numberOfSockets = 0;
- Boolean weInstalled = false;
-
- IfDebugStr("\pPCCardClient");
-
- // only run if the PC Card manager is available
-
- if (PCCardManagerIsAvailable(&numberOfSockets) && (numberOfSockets != 0))
- {
- THz savedZone = GetZone();
-
- SetZone(SystemZone());
- weInstalled = (InstallPCCardClient(numberOfSockets) == noErr);
- SetZone(savedZone);
- }
-
- if (weInstalled)
- {
- DetachResource(me); // make sure we don’t disappear if we loaded!
- // ShowINIT(kExtensionIconID);
- }
- // else
- // ShowINIT(kExtensionNotLoadedIconID);
- }
-
-
- Boolean
- PCCardManagerIsAvailable(UInt32 * numberOfSockets)
- {
- long featureFlags;
- OSErr err;
-
- err = Gestalt(gestaltCardServicesAttr,&featureFlags);
- if (err == noErr)
- {
- if (featureFlags & (1 << gestaltCardServicesPresent))
- {
- GetCardServicesInfoPB csInfoPB;
- Str255 vendorString;
-
- csInfoPB.reserved = 0;
- csInfoPB.vStrLen = sizeof(vendorString)-1;
- csInfoPB.vendorString = &vendorString[1];
-
- if ( CSGetCardServicesInfo(&csInfoPB) == noErr )
- {
- *numberOfSockets = csInfoPB.count;
- return true;
- }
- }
- }
-
- return false;
- }
-
-
- OSErr
- InstallPCCardClient(UInt32 numberOfSockets)
- {
- OSErr err;
- RegisterClientPB registerClientPB;
- VendorSpecificPB vendorSpecificPB;
- PCCardClientGlobalsRec * globals;
-
- // Allocate our globals, note that we allocate additional per-socket
- // state so that our client can track multiple cards
-
- globals = (PCCardClientGlobalsRec *) NewPtrSysClear(sizeof(PCCardClientGlobalsRec)
- + (numberOfSockets * sizeof(PCCardPerSocketState)));
- if (globals == NULL)
- return MemError();
-
- globals->numberOfSockets = numberOfSockets;
-
- // fetch description strings & icons (vendor information for this client)
- // from our resource fork
-
- GetIndString(globals->cardName, kCardStringList, kCardName);
- GetIndString(globals->cardType, kCardStringList, kCardType);
- GetIndString(globals->vendorName, kCardStringList, kCardVendorName);
- GetIndString(globals->clientName, kCardStringList, kCardClientName);
-
- if (GetIconSuite(&globals->cardIconSuite, kCardIconID, svAllAvailableData) != noErr)
- globals->cardIconSuite = NULL;
-
- if (globals->cardIconSuite) // If there are icons, detach them
- ForEachIconDo(globals->cardIconSuite, svAllAvailableData, NewIconActionProc(DetachIcons), 0);
-
-
- // register our client
-
- registerClientPB.clientEntry = NewPCCardCSClientProc(HandlePCCardEvent);
- registerClientPB.attributes = kPCCardClientAttributes;
- registerClientPB.eventMask = kInterestingPCCardEvents;
- registerClientPB.clientData = (void *) globals;
- registerClientPB.version = 0x210;
-
- err = CSRegisterClient(®isterClientPB);
- if (err != noErr)
- return err;
-
- globals->clientHandle = registerClientPB.clientHandle;
-
-
- // enable socket events for our client
-
- vendorSpecificPB.clientHandle = globals->clientHandle;
- vendorSpecificPB.vsCode = vsEnableSocketEvents;
- vendorSpecificPB.socket = 0;
- vendorSpecificPB.dataLen = 0;
- vendorSpecificPB.vsDataPtr = nil;
-
- err = CSVendorSpecific(&vendorSpecificPB);
- if (err != noErr)
- (void) CSDeregisterClient(®isterClientPB);
-
- return err;
- }
-
-
-
- pascal
- OSErr HandlePCCardEvent(ClientCallbackPBPtr pb)
- {
- PCCardClientGlobalsRec * globals = (PCCardClientGlobalsRec *) pb->clientData;
- PCCardPerSocketState * socketState = &(globals->socketState[pb->socket]);
- OSErr result = noErr;
-
- switch (pb->message)
- {
- case kCSFunctionInterruptMessage: // FUNCTION_INTERRUPT
- if (socketState->cardFlags & kCardIsConfigured)
- MyCardInterruptHandler(globals,socketState,pb->socket);
- break;
-
- case kCSCardRemovalMessage: // CARD_REMOVAL
- result = HandleCardRemoval(globals,socketState,pb);
- break;
-
- case kCSEjectionRequestMessage: // EJECTION_REQUEST
- result = HandleCardEjectRequest(globals,socketState,pb);
- break;
-
- case kCSCardReadyMessage: // CARD_READY
- // If it is configured we don't have to do anything
- if (socketState->cardFlags & kCardIsConfigured)
- break;
-
- result = HandleCardReady(globals,socketState,pb);
- break;
-
- case kCSClientInfoMessage: // CLIENT_INFO
- result = HandleGetClientInfo(globals,(GetClientInfoPB *) pb->buffer);
- break;
-
- case kCSPMResumeMessage: // PM_RESUME
- result = HandleCardResume(globals,pb);
- break;
-
- case kCSPMSuspendMessage: // PM_SUSPEND
- if (socketState->cardFlags & kCardIsConfigured)
- result = HandleCardSuspend(globals,pb);
- break;
-
- default:
- break;
- }
-
- return result;
- }
-
-
- OSErr HandleCardReady(PCCardClientGlobalsRec * globals,PCCardPerSocketState * socketState, ClientCallbackPBPtr pb)
- {
- IfDebugStr("\pCARD READY");
-
- if (IsThisMyCard(globals,pb->socket))
- if (ConfigureMyCard(globals,socketState,pb->socket) == noErr)
- {
- socketState->cardFlags |= kCardIsConfigured;
- return noErr;
- }
-
- // Once we have detected that a card is not for us (after CARD_READY is received
- // for a card wedon’t recognize) we mask out all events for that socket, except
- // for card removal. Once we get a card removal, we will ask for all our interesting
- // events.
-
- SetClientEventMaskForSocket(globals,pb->socket,kCSCardDetectChangeEvent);
-
- return kCSUnsupportedFunctionErr;
- }
-
-
- OSErr HandleCardRemoval(PCCardClientGlobalsRec * globals,PCCardPerSocketState * socketState, ClientCallbackPBPtr pb)
- {
- IfDebugStr("\pCARD REMOVAL");
-
- if (socketState->cardFlags & kCardIsConfigured)
- {
- // If we haven’t released our configuration, go ahead an do that
-
- (void) UnconfigureMyCard(globals,socketState,pb->socket);
- }
-
-
- // Make sure our slate is clean
-
- socketState->cardFlags = 0;
-
- // Once we have detected that a card has been removed (via CARD_REMOVAL)
- // we reset the event mask so that we can catch all pertinent events for
- // the next card
-
- SetClientEventMaskForSocket(globals,pb->socket, kInterestingPCCardEvents);
-
- return noErr;
- }
-
-
- OSErr HandleCardEjectRequest(PCCardClientGlobalsRec * globals,PCCardPerSocketState * socketState, ClientCallbackPBPtr pb)
- {
- if (socketState->cardFlags & kCardIsConfigured)
- {
- IfDebugStr("\pEJECT REQUEST");
-
- (void) UnconfigureMyCard(globals,socketState,pb->socket);
- socketState->cardFlags = 0;
-
- return noErr;
- }
-
- return noErr;
- }
-
-
- OSErr HandleGetClientInfo(PCCardClientGlobalsRec * globals, GetClientInfoPB * pb)
- {
- OSErr result = kCSUnsupportedFunctionErr;
- PCCardPerSocketState * socketState;
- UInt16 subFunction = (pb->u.clientInfo.attributes & kCSInfoSubfunctionMask);
-
- if (subFunction == kCSClientInfoSubfunction)
- {
- IfDebugStr("\pNormal GETCLIENTINFO");
-
- pb->u.clientInfo.revision = kMyClientVersion; /* <- BCD value of client's revision*/
- pb->u.clientInfo.csLevel = kRequiredCSLevel; /* <- BCD value of CS release*/
- pb->u.clientInfo.revDate = kMyClientRevisionDate; /* <- revision date: y[15-9], m[8-5], d[4-0]*/
-
- // provide our name string, if they want it
-
- CopyPStringToBoundedCString(globals->clientName,
- (char *) pb->u.clientInfo.nameString,
- (UInt16 *) &pb->u.clientInfo.nameLen);
-
- // ...and/or our vendor string
-
- CopyPStringToBoundedCString(globals->vendorName,
- (char *) pb->u.clientInfo.vendorString,
- (UInt16 *) &pb->u.clientInfo.vStringLen);
-
- return noErr;
- }
-
- socketState = &(globals->socketState[pb->u.alternateTextString.socket]);
-
- if (socketState->cardFlags & kCardIsConfigured)
- {
- switch (subFunction)
- {
- case kCSCardNameSubfunction:
- IfDebugStr("\pkCSCardNameSubfunction");
- if (globals->cardName[0]) // If we have a custom card name, return it.
- {
- CopyPStringToBoundedCString(globals->cardName,
- (char *) pb->u.alternateTextString.text,
- (UInt16 *) &pb->u.alternateTextString.length);
- result = noErr;
- }
- break;
-
- case kCSCardTypeSubfunction:
- IfDebugStr("\pkCSCardTypeSubfunction");
- if (globals->cardType[0]) // If we have a custom card type, return it.
- {
- CopyPStringToBoundedCString(globals->cardType,
- (char *) pb->u.alternateTextString.text,
- (UInt16 *) &pb->u.alternateTextString.length);
- result = noErr;
- }
- break;
-
- case kCSHelpStringSubfunction:
- IfDebugStr("\pkCSHelpStringSubfunction");
- if (globals->helpString[0]) // If we have a help balloon string, return it.
- {
- CopyPStringToBoundedCString(globals->helpString,
- (char *) pb->u.alternateTextString.text,
- (UInt16 *) &pb->u.alternateTextString.length);
- result = noErr;
- }
- break;
-
- case kCSCardIconSubfunction:
- IfDebugStr("\pkCSCardIconSubfunction");
- if (globals->cardIconSuite) // If we have a custom icon, return it.
- {
- pb->u.alternateIcon.iconSuite = globals->cardIconSuite;
- result = noErr;
- }
- break;
-
- case kCSActionProcSubfunction:
- IfDebugStr("\pkCSActionProcSubfunction");
- break;
-
- default:
- IfDebugStr("\pUnknown GetClientInfo variant");
- break;
- }
- }
-
- return result;
- }
-
-
- OSErr HandleCardSuspend(PCCardClientGlobalsRec * /* globals */,ClientCallbackPBPtr /* pb */)
- {
- // IfDebugStr("\pPM SUSPEND");
-
- return noErr;
- }
-
-
- OSErr HandleCardResume(PCCardClientGlobalsRec * /* globals */,ClientCallbackPBPtr /* pb */)
- {
- // IfDebugStr("\pPM RESUME");
-
- return noErr;
- }
-
-
-
-
- // SetClientEventMaskForSocket
- //
- // a wrapper function for CSSetClientEventMask to make the code more readable
-
- void
- SetClientEventMaskForSocket(PCCardClientGlobalsRec * globals, UInt16 socket, UInt16 eventMask)
- {
- GetSetClientEventMaskPB eventMaskPB;
-
- eventMaskPB.clientHandle = globals->clientHandle;
- eventMaskPB.socket = socket;
- eventMaskPB.attributes = kCSEventMaskThisSocketOnly;
- eventMaskPB.eventMask = eventMask;
-
- CSSetClientEventMask(&eventMaskPB);
- }
-
-
- // CopyPStringToBoundedCString
- //
- // a utility function called by HandleGetClientInfo which is used to copy
- // strings into a clients buffer.
-
- void
- CopyPStringToBoundedCString(StringPtr sourcePString,char * destCString,UInt16 *size)
- {
- UInt32 strLen = *size;
-
- if ( strLen != 0 )
- {
- if (sourcePString[0] < strLen)
- strLen = sourcePString[0] + 1;
-
- BlockMoveData(&sourcePString[1], destCString, strLen-1);
- destCString[strLen-1] = 0;
- *size = strLen;
- }
- }
-
-
- // DetachIcons
- //
- // an IconActionProc which detaches an icon family from the extension file,
- // and keeps it around.
-
- pascal OSErr
- DetachIcons(ResType resType, Handle *hdl, void * /* p */)
- {
- if (hdl)
- {
- if (resType)
- {
- LoadResource(*hdl);
- HNoPurge(*hdl);
- DetachResource(*hdl);
- }
- }
-
- return noErr;
- }
-